#include <Poco/Data/MySQL/Connector.h>
#include <Poco/Data/SQLite/Connector.h>
#include <iostream>

#include "../../include/CLink/database/ConnectionPool.h"

namespace CLink{
namespace Db {

ConnectionPool::ConnectionPool(const ConnectionConfig& config)
    : _config(config)
    , _shutdown(false) {
    
    // 注册数据库连接器
    static bool registered = false;
    if (!registered) {
#ifdef _WIN32
        // Windows平台支持MySQL
        Poco::Data::MySQL::Connector::registerConnector();
#endif
        // 所有平台都支持SQLite
        Poco::Data::SQLite::Connector::registerConnector();
        registered = true;
    }
    
    // 创建连接池
    try {
        std::string connectorName;
        switch (config.type) {
            case DatabaseType::MYSQL:
#ifdef _WIN32
                connectorName = "MySQL";
                break;
#else
                throw ConnectionException("MySQL数据库在当前平台不支持");
#endif
            case DatabaseType::SQLITE:
                connectorName = "SQLite";
                break;
            default:
                throw ConnectionException("error databse type");
        }
        
        _pool = std::make_unique<Poco::Data::SessionPool>(
            connectorName,
            config.createConnectionString(),
            config.minSessions,
            config.maxSessions,
            config.idleTime
        );
    } catch (const Poco::Exception& e) {
        throw ConnectionException("创建连接池失败: " + std::string(e.what()));
    }
}

ConnectionPool::~ConnectionPool() {
    shutdown();
}

ConnectionPool::ConnectionPtr ConnectionPool::getConnection(std::chrono::milliseconds timeout) {
    std::unique_lock<std::mutex> lock(_mutex);
    
    if (_shutdown) {
        throw PoolException("连接池已关闭");
    }
    
    try {
        // 尝试从池中获取连接
        auto session = _pool->get();
        session << "SELECT 1" << Poco::Data::Keywords::now;
        return std::make_shared<Connection>(session);;
    } catch (const Poco::Exception& e) {
        throw ConnectionException("获取连接失败: " + std::string(e.what()));
    }
}

void ConnectionPool::releaseConnection(ConnectionPtr connection) {
    // Poco::Data::SessionPool 会自动管理连接的释放
    // 当 Connection 对象被销毁时，其中的 Session 会自动返回到池中
}

size_t ConnectionPool::getActiveConnections() const {
    std::unique_lock<std::mutex> lock(_mutex);
    return _pool->used();
}

size_t ConnectionPool::getIdleConnections() const {
    std::unique_lock<std::mutex> lock(_mutex);
    return _pool->capacity() - _pool->used();
}

void ConnectionPool::shutdown() {
    std::unique_lock<std::mutex> lock(_mutex);
    
    if (!_shutdown) {
        _shutdown = true;
        _pool->shutdown();
    }
}

ConnectionPool::ConnectionPtr ConnectionPool::createConnection() {
    try {
        auto session = _pool->get();
        return std::make_shared<Connection>(std::move(session));
    } catch (const Poco::Exception& e) {
        throw ConnectionException("创建连接失败: " + std::string(e.what()));
    }
}

bool ConnectionPool::validateConnection(Connection& conn) {
    try {
        // 执行简单查询来验证连接
        conn.getSession() << "SELECT 1", Poco::Data::Keywords::now;
        return true;
    } catch (std::exception e) {
		std::string msg = e.what();
        return false;
    }
}

} // namespace db
} // namespace CLink